package com.muyangren.utils;


import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.Result;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TextProperty;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import co.elastic.clients.transport.endpoints.BooleanResponse;
import com.muyangren.constants.EsConstant;
import com.muyangren.entity.TransEsContent;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;

/**
 * @author guangsheng
 * @Date: 2022/7/14
 * @Description: 重构ES方法，解决代码重复问题 方法大致如此，细节需要自己去打磨
 * @Version: 1.0
 */
@Component
public class ElasticSearchUtils {

    /**
     * 判断索引(index)是否存在,不存在就创建
     */
    public static Boolean whetherIndex(ElasticsearchClient esClient, String index, String analyzer) {
        BooleanResponse getIndexResponse;
        boolean whetherIndex = false;
        try {
            getIndexResponse = esClient.indices().exists(e -> e.index(index));
            whetherIndex = getIndexResponse.value();
            if (Boolean.FALSE.equals(whetherIndex)) {
                whetherIndex = ElasticSearchUtils.addIndex(esClient, index, analyzer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return whetherIndex;
    }

    /**
     * 添加索引
     * 分析器主要有两种情况会被使用：
     * 第一种是插入文档时，将text类型的字段做分词然后插入倒排索引，
     * 第二种就是在查询时，先对要查询的text类型的输入做分词，再去倒排索引搜索
     * analyzer: 分词器
     * searchAnalyzer： 查询分词器
     */
    public static Boolean addIndex(ElasticsearchClient esClient,String index,String analyzer){
        boolean whetherTrue =false;
        try {
            // 配置索引
            Map<String, Property> property = new HashMap<>(1);
            property.put(EsConstant.CONTENT, new Property(new TextProperty.Builder()
                    .analyzer(analyzer)
                    .searchAnalyzer(analyzer)
                    .index(true)
                    .store(true)
                    .build()));
            TypeMapping typeMapping = new TypeMapping.Builder()
                    .properties(property)
                    .build();
            IndexSettings indexSettings  = new IndexSettings.Builder()
                    .numberOfShards("2")
                    .build();
            CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder()
                    .index(index)
                    .mappings(typeMapping)
                    .settings(indexSettings)
                    .build();
            CreateIndexResponse createIndexResponse = esClient.indices().create(createIndexRequest);
            whetherTrue = Boolean.TRUE.equals(createIndexResponse.acknowledged());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return whetherTrue;
    }

    /**
     * ES添加方法
     */
    public static void addEsTransfer(ElasticsearchClient esClient, TransEsContent transEsContent, String index) {
        try {
            CreateResponse createResponse = esClient.create(e -> e
                    .index(index)
                    .id(String.valueOf(transEsContent.getId()))
                    .document(transEsContent));
            Result result = createResponse.result();
            //自行处理
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 批量同步数据
     * 批量超过一万条会超时，建议使用分页解决，每次插入五百条 //todo 后续会优化
     */
    public static Long addAllEsTransfer(ElasticsearchClient esClient, List<TransEsContent> transList, String index) {
        try {
            BulkRequest.Builder builder = new BulkRequest.Builder();
            for (TransEsContent trans : transList) {
                builder.operations(op -> op
                        .index(idx -> idx
                                .index(index)
                                .id(String.valueOf(trans.getId()))
                                .document(trans)));
            }
            BulkResponse result;
            result = esClient.bulk(builder.build());
            List<BulkResponseItem> items = result.items();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * ES更新方法
     */
    public static void updateEsTransfer(TransEsContent transEsContent, ElasticsearchClient esClient, String index) {
        try {
            //1)先查看是否存在ES服务中
            GetRequest.Builder builder = new GetRequest.Builder();
            GetRequest transfer = builder.index(index).id(String.valueOf(transEsContent.getId())).build();
            GetResponse<TransEsContent> getResponse = esClient.get(transfer, TransEsContent.class);
            TransEsContent source = getResponse.source();
            //2)先根据id查询是否存在该数据
            if (source == null) {
                //2.1)新增操作
                addEsTransfer(esClient, transEsContent, index);
            } else {
                //2.2)更新操作
                UpdateResponse<TransEsContent> updateResponse;
                updateResponse = esClient.update(e -> e
                                .index(index)
                                .id(String.valueOf(transEsContent.getId()))
                                .doc(transEsContent)
                        , TransEsContent.class);
                Result result = updateResponse.result();
                //自行处理
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 批量删除ES服务器中的数据
     */
    public static Boolean asyncDelEsTransfer(List<Integer> list, ElasticsearchClient esClient, String index) {
            try {
                ArrayList<BulkOperation> bulkOperations = new ArrayList<>();
                for (Integer aLong : list) {
                    bulkOperations.add(new BulkOperation.Builder()
                            .delete(d -> d
                                    .id(String.valueOf(aLong))
                                    .index(index))
                            .build());
                }
                BulkResponse bulkResponse = esClient.bulk(e -> e.index(index).operations(bulkOperations));
                //自行处理
            } catch (IOException e) {
                e.printStackTrace();
            }
            return true;
    }
    /**
     * 删除ES服务器中的数据
     */
    public static Boolean asyncDelEsTransfer(Integer id, ElasticsearchClient esClient, String index) {
        Boolean bool =false;
        try {
            BulkOperation build = new BulkOperation.Builder()
                    .delete(d -> d
                            .id(String.valueOf(id))
                            .index(index))
                    .build();
            BulkResponse bulkResponse = esClient.bulk(e -> e.index(index).operations(build));
            BulkResponseItem items = bulkResponse.items().get(0);
            if (items.status() == 200){
                bool=Boolean.TRUE;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bool;
    }

    public static Boolean retBool (Integer result) {
        return null !=result && result >= 1;
    }
}
